package Second;

import java.util.Scanner;

/**
 * @author 长风无言
 */
public class Wuziqi {

    String [][] arr1 = new String[17][17];

    Boolean playerFlag = true;                                 
/**
 * description:初始化二维数组
 *
 * @return void
 */
    void iniArr1(){
        arr1[0][0]= String.valueOf(' ');
        for (int i=1;i<=16;i++) {
            //第一行初始化赋值
            arr1[0][i] = Integer.toHexString(i-1);           
        }

        for(int i=1;i<17;i++) {
            //第一列初始化赋值
            arr1[i][0] = Integer.toHexString(i - 1);         
            for(int j=1;j<17;j++){
                //其余全部给"+"号
                arr1[i][j]="+";                                
            }
        }
    }
/**
 * description: 打印出二维数组
 *
 * @return void
 */
    void drawBoard(){                                           
        for(int i=0;i<17;i++){
            for(int j=0;j<17;j++){
                //每一个符号后面接一个空格，避免制台显示显示结果过于紧凑
                System.out.print(arr1[i][j]+" ");
            }
            //每打印完一行换行
            System.out.println("");                              
        }
    }
/**
 * description: 开始下棋
 *
 * @return void
 */
    void playGame(){                                           
        //分别记录横纵坐标
        int pointX,pointY;
        //判断标志位，用于记录是否出现违规操作。违规操作包括：1、落子位置已有棋子。2、落子位置超出棋盘。
        boolean checkFlag;                                       

        System.out.println("请"+(playerFlag? "黑":"白")+"棋落子：(X Y)");

        do {
            //循环最开始位置置标志位为false,避免多次连续的违规操作
            checkFlag = false;                                                    

            Scanner chess = new Scanner(System.in);                             
            pointX = chess.nextInt();                                            
            pointY = chess.nextInt();                                           

            //判断落子位置是否超出棋盘
            if (pointX > 16 || pointY > 16 || pointX < 0 || pointY < 0) {      
                System.out.println("坐标超出棋盘，请重新输入0~15的横纵坐标：(X,Y)");
                //检测到违规操作标志位取反置true
                checkFlag =!checkFlag;  
                //检测落子位置是否已有棋子
            }else if(!"+".equals(arr1[pointY + 1][pointX + 1])){
                System.out.println("该位置已有棋子，请参考棋盘重新输入横纵坐标：(X,Y)");
                //检测到违规操作标志位取反置true
                checkFlag =!checkFlag;                                           
            }else {
                //无违规操作根据选手标志位判定下黑棋还是白棋。@为黑棋，o为白棋
                arr1[pointY + 1][pointX + 1] = playerFlag ? "@" : "o"; 
                //选手标志位取反表示换一个棋手下棋
                playerFlag = !playerFlag;                                     
            }
            //根据违规操作检测结果决定是否进去循环重新落子
        }while(checkFlag);                                                        
    }
/**
 * description: 胜负判断函数
 *
 * @return int
 */
    int victoryDefeat(){  
        //用于记录是否已有人获胜。1表示有，0表示无
        int judgeFlag = 0;
        //获得行列检测函数返回值
        judgeFlag = checkLineColumn();
        //若行列检测无连续同色五子
        if(0==judgeFlag){     
            //活动斜行列检测函数返回值
            judgeFlag = checkDiagLine();
        }
        //如果已经分出胜负
        if(1==judgeFlag) {                                                       
            System.out.println("最后结果如下：");
            //打印最后的结果
            drawBoard();                                                          
        }
        //返回值告诉main函数是否继续游戏
        return judgeFlag;                                                       
    }
/**
 * description: 检测行列是否有五个连续的同色棋子
 * 
 * @return int
 */
    int  checkLineColumn(){                                                        

        //用于记录行列连续棋子数
        int blackNum=0, whiteNum = 0;
        int blackNum1=0, whiteNum1 = 0;

        for(int i=1;i<17;i++){
            for(int j=1;j<17;j++){
                /*
                * 如果当前位置是白子
                * 白子连续数目加一
                * 黑子连续数目重置
                * */
                if("o".equals(arr1[i][j])){
                    whiteNum += 1;                                                 
                    blackNum = 0;
                    //原理同上
                }else if("@".equals(arr1[i][j])){                                    
                    blackNum += 1;                                                 
                     whiteNum = 0;
                     //如当前位置没有棋子，则黑白棋连续数目都置0
                }else{                                                                
                    blackNum = 0;                                                
                     whiteNum = 0;
                }
                //i,j位置交换即可检测列，原理与上面一样
                if("o".equals(arr1[j][i])){                                          
                     whiteNum1 += 1;
                    blackNum1 = 0;
                }else if("@".equals(arr1[j][i])){
                    blackNum1 += 1;
                     whiteNum1 = 0;
                }else{
                    blackNum1 = 0;
                     whiteNum1= 0;
                }
                //若任意检测函数检测到连续五子
                if( 5 == whiteNum || 5 == blackNum || 5 ==  whiteNum1 || 5 == blackNum1 ) {
                    //判断获胜方并打印获胜信息
                    System.out.println("恭喜" + (( 5 ==  whiteNum || 5 == whiteNum1 ) ? "白棋" : "黑棋") + "获得胜利");
                    //返回1表明已有人获胜并跳出循环
                    return 1;                                                                                          
                }
            }
        }
        //表明没有人获胜，返回0
         return 0;
    }

/**
 * description: 检测斜行列
 *
 * @return int
 */

    int checkDiagLine(){

        /*
         * 记录第一行为准的左上到右下连续同色棋子数
         * 记录第一行为准的右上到左下连续同色棋子数
         * 记录第一列为准的左上到右下连续同色棋子数
         * 记录最后一列为准的右上到左下连续同色棋子数
         */
        int blackNum=0,whiteNum = 0;
        int blackNum1=0,whiteNum1 = 0;                                            
        int blackNum2=0,whiteNum2 = 0;                                           
        int blackNum3=0,whiteNum3 = 0;
        int i,j;

        //因为第14行开始斜列最多只有4个落子位置，不可能出现连续同色五子，所以最后四行斜行列不用检查
        for(int n=1;n<14;n++){

            i=1;
            j=n;

            //初始横坐标和纵坐标最大值合为固定值17
            while(i<18-n){

                //检测原理同上
                if("o".equals(arr1[i][j])){
                    whiteNum += 1;
                    blackNum = 0;
                }else if("@".equals(arr1[i][j])){
                    blackNum += 1;
                    whiteNum = 0;
                }else{
                    blackNum = 0;
                    whiteNum = 0;
                }
                //右上到左下和左上到右下关系为：行相同，列合为17
                if("o".equals(arr1[i][17 - j])){
                    whiteNum1 += 1;
                    blackNum1 = 0;
                }else if("@".equals(arr1[i][17 - j])){
                    blackNum1 += 1;
                    whiteNum1 = 0;
                }else{
                    blackNum1 = 0;
                    whiteNum1 = 0;
                }
                //列为准的左上到右下与行为准的左上到右下关系为：行与对方的列相等，列与对方的行相等，即i,j交换位置
                if("o".equals(arr1[j][i])){
                    whiteNum2 += 1;
                    blackNum2 = 0;
                }else if("@".equals(arr1[j][i])){
                    blackNum2 += 1;
                    whiteNum2 = 0;
                }else{
                    blackNum2 = 0;
                    whiteNum2 = 0;
                }
                //第一列为准的左上到右下和最后一列右上到左下关系为：行相同，列和为17
                if("o".equals(arr1[j][17-i])){
                    whiteNum3 += 1;
                    blackNum3 = 0;
                }else if("@".equals(arr1[j][17-i])){
                    blackNum3 += 1;
                    whiteNum3 = 0;
                }else{
                    blackNum3 = 0;
                    whiteNum3 = 0;
                }
                //移动坐标
                i++;
                j++;
                //任意一个模块判断到五个同色棋子
                if(5 ==whiteNum || 5 == blackNum || 5 == whiteNum1 || 5 == blackNum1 || 5 == whiteNum2 || 5 == whiteNum3 || 5 == blackNum2 || 5 == blackNum3) {
                    //判定获胜方并输出语句
                    System.out.println("恭喜" + (( 5 == whiteNum || 5 ==whiteNum1 ||  5 == whiteNum2 || 5 ==whiteNum3 ) ? "白棋" : "黑棋") + "获得胜利");
                    return 1;
                }
            }

        }
        //没有人获胜
        return 0;
    }
/**
 * description:
 *
 * @param args 语句
 * @return void
 */
    public static void main(String[] args) {

        //判断标志位，用于记录是否已经分出胜负
        int judgeFlag = 0;
        //创建新对象
        Wuziqi board = new Wuziqi();
        //初始化二维数组
        board.iniArr1();
        //当还未分出胜负时
        while(0 == judgeFlag) {
            //打印二维数组
            board.drawBoard();
            //选手轮流下棋
            board.playGame();
            //判断是否有人分出胜负
            judgeFlag = board.victoryDefeat();

        }

    }
}
